#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import http.server
import socketserver
import json
import urllib.parse
from urllib.parse import urlparse, parse_qs
import webbrowser
import os
import requests
import pandas as pd
from datetime import datetime, timedelta

# 新增导入：铁路API与DeepSeek
try:
    from simple_railway_api import RailwayAPI
except Exception:
    RailwayAPI = None

try:
    from api_keys_complete import DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, DEEPSEEK_MODEL
except Exception:
    DEEPSEEK_API_KEY, DEEPSEEK_BASE_URL, DEEPSEEK_MODEL = None, None, None

# 聚合数据配置
try:
    from api_keys_complete import JUHE_TRAIN_APPKEY, JUHE_TRAIN_ENABLED
    from api_keys_complete import JUHE_FLIGHT_APPKEY, JUHE_FLIGHT_ENABLED, JUHE_FLIGHT_MAX_SEGMENTS
except Exception:
    JUHE_TRAIN_APPKEY, JUHE_TRAIN_ENABLED = None, False
    JUHE_FLIGHT_APPKEY, JUHE_FLIGHT_ENABLED, JUHE_FLIGHT_MAX_SEGMENTS = None, False, 1

# 高德API
try:
    from backend.gaode_api import GaodeAPI
except Exception:
    GaodeAPI = None

try:
    from api_keys_complete import GAODE_API_KEY as GAODE_KEY
except Exception:
    try:
        from api_keys import GAODE_API_KEY as GAODE_KEY
    except Exception:
        GAODE_KEY = None

# 可选：使用openai官方客户端兼容DeepSeek
try:
    import openai
    OpenAIClient = openai.OpenAI  # 兼容openai>=1.0.0
except Exception:
    OpenAIClient = None

# 初始化API客户端
_gaode_api = GaodeAPI(GAODE_KEY) if GAODE_KEY else None
_railway_api = RailwayAPI() if RailwayAPI else None

# 聚合数据客户端
try:
    from backend.train_api import TrainJuheClient, FlightJuheClient
    _juhe_client = TrainJuheClient(JUHE_TRAIN_APPKEY) if (JUHE_TRAIN_ENABLED and JUHE_TRAIN_APPKEY) else None
    _juhe_flight_client = FlightJuheClient(JUHE_FLIGHT_APPKEY, JUHE_FLIGHT_MAX_SEGMENTS) if (JUHE_FLIGHT_ENABLED and JUHE_FLIGHT_APPKEY) else None
except Exception:
    _juhe_client = None
    _juhe_flight_client = None

# 周边城市映射
NEARBY_CITIES = {
    '大连': ['沈阳', '营口', '丹东', '鞍山'],
    '合肥': ['南京', '武汉', '郑州', '济南'],
    '北京': ['天津', '石家庄', '保定', '廊坊'],
    '上海': ['南京', '杭州', '苏州', '无锡'],
    '广州': ['深圳', '佛山', '东莞', '中山'],
    '深圳': ['广州', '东莞', '惠州', '佛山'],
    '南京': ['上海', '合肥', '苏州', '无锡'],
    '杭州': ['上海', '南京', '宁波', '绍兴'],
    '武汉': ['长沙', '郑州', '合肥', '南昌'],
    '成都': ['重庆', '西安', '贵阳', '昆明'],
    '重庆': ['成都', '贵阳', '西安', '武汉'],
    '西安': ['郑州', '太原', '兰州', '成都'],
    '天津': ['北京', '石家庄', '唐山', '保定'],
    '青岛': ['济南', '烟台', '威海', '潍坊'],
    '沈阳': ['大连', '长春', '哈尔滨', '鞍山'],
    '哈尔滨': ['长春', '沈阳', '大庆', '齐齐哈尔']
}

# 加载本地高铁数据
def load_local_train_data():
    """加载本地高铁数据"""
    train_data = []
    
    # 尝试从Excel文件加载
    excel_files = [
        '../全国高铁区间票价明细表_去重版.xlsx',
        '全国高铁区间票价明细表_去重版.xlsx',
        '../crawler_lab/全国高铁区间票价明细表_去重版.xlsx'
    ]
    
    for excel_file in excel_files:
        if os.path.exists(excel_file):
            try:
                print(f"📊 尝试加载Excel文件: {excel_file}")
                df = pd.read_excel(excel_file)
                print(f"📊 从 {excel_file} 加载了 {len(df)} 条数据")
                print(f"📋 列名: {list(df.columns)}")
                
                # 转换为统一格式
                for _, row in df.iterrows():
                    try:
                        # 根据实际列名调整
                        origin = str(row.get('出发站', row.get('出发地', row.get('起点', ''))))
                        destination = str(row.get('到达站', row.get('目的地', row.get('终点', ''))))
                        price = row.get('票价', row.get('价格', row.get('二等座', 0)))
                        train_no = row.get('车次', row.get('列车号', row.get('车次号', '')))
                        
                        if origin and destination and price:
                            train_data.append({
                                'type': 'train',
                                'train_number': str(train_no) if train_no else 'G' + str(len(train_data) + 1).zfill(4),
                                'train_type': '高铁',
                                'origin': origin,
                                'destination': destination,
                                'dep_time': '2025-09-20 08:00',  # 默认时间
                                'arr_time': '2025-09-20 16:00',  # 默认时间
                                'price': int(float(price)) if price else 0,
                                'dep_station': origin,
                                'arr_station': destination,
                                'duration': '8小时',  # 默认时长
                                'seat_type': '二等座',
                                'is_high_speed': '是',
                                'source': '本地Excel数据',
                                'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                            })
                    except Exception as e:
                        print(f"  ❌ 解析Excel行异常: {e}")
                        continue
                
                break  # 成功加载一个文件就退出
                
            except Exception as e:
                print(f"❌ 加载Excel文件失败: {e}")
                continue
    
    # 如果没有找到数据，生成一些示例高铁数据
    if not train_data:
        print("📝 生成示例高铁数据")
        train_data = [
            {
                'type': 'train',
                'train_number': 'G1234',
                'train_type': '高铁',
                'origin': '大连',
                'destination': '合肥',
                'dep_time': '2025-09-20 08:30',
                'arr_time': '2025-09-20 16:45',
                'price': 580,
                'dep_station': '大连北站',
                'arr_station': '合肥南站',
                'duration': '8小时15分',
                'seat_type': '二等座',
                'is_high_speed': '是',
                'source': '示例数据',
                'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            },
            {
                'type': 'train',
                'train_number': 'G5678',
                'train_type': '高铁',
                'origin': '大连',
                'destination': '合肥',
                'dep_time': '2025-09-20 14:20',
                'arr_time': '2025-09-20 22:35',
                'price': 620,
                'dep_station': '大连北站',
                'arr_station': '合肥南站',
                'duration': '8小时15分',
                'seat_type': '二等座',
                'is_high_speed': '是',
                'source': '示例数据',
                'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
        ]
    
    print(f"✅ 加载了 {len(train_data)} 条高铁数据")
    return train_data

# 全局高铁数据
LOCAL_TRAIN_DATA = load_local_train_data()

def calculate_duration(dep_time, arr_time):
    """计算行程时间"""
    try:
        if dep_time and arr_time:
            # 处理不同的时间格式
            if len(dep_time) == 5:  # HH:MM格式
                dep = datetime.strptime(dep_time, '%H:%M')
                arr = datetime.strptime(arr_time, '%H:%M')
            else:  # 完整日期时间格式
                dep = datetime.strptime(str(dep_time), '%Y-%m-%d %H:%M')
                arr = datetime.strptime(str(arr_time), '%Y-%m-%d %H:%M')
            
            duration = arr - dep
            hours = duration.seconds // 3600
            minutes = (duration.seconds % 3600) // 60
            
            if hours > 0:
                return f"{hours}小时{minutes}分" if minutes > 0 else f"{hours}小时"
            else:
                return f"{minutes}分钟"
    except Exception as e:
        print(f"❌ 计算时间异常: {e}")
    return "未知"

class MyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        path = urlparse(self.path).path
        query_params = parse_qs(urlparse(self.path).query)
        
        if path == '/':
            self.send_response(302)
            self.send_header('Location', '/frontend/index.html')
            self.end_headers()
        elif path == '/frontend/index.html':
            self.serve_frontend()
        elif path == '/api/status':
            self.send_api_status()
        elif path == '/api/cities':
            self.send_cities()
        elif path == '/api/test':
            self.send_test_response()
        else:
            self.send_error(404)
    
    def do_POST(self):
        path = urlparse(self.path).path
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        
        try:
            data = json.loads(post_data.decode('utf-8'))
        except:
            data = {}
        
        if path == '/api/search':
            self.send_search_result(data)
        elif path == '/api/poi':
            self.send_poi_search(data)
        elif path == '/api/geocode':
            self.send_geocode(data)
        else:
            self.send_error(404)
    
    def serve_frontend(self):
        try:
            with open('frontend/index.html', 'r', encoding='utf-8') as f:
                content = f.read()
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(content.encode('utf-8'))
        except FileNotFoundError:
            self.send_error(404)
    
    def send_api_status(self):
        status = {
            'status': 'success',
            'message': '增强版服务器运行正常',
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'features': [
                '真实机票数据获取（聚合数据API）',
                '本地Excel高铁数据加载',
                '周边城市智能对比',
                '智能排序和推荐',
                'DeepSeek AI集成'
            ],
            'apis': {
                'flight': 'enabled' if _juhe_flight_client else 'disabled',
                'train': 'enabled (本地Excel数据)',
                'nearby': 'enabled',
                'smart_sort': 'enabled',
                'deepseek': 'enabled' if DEEPSEEK_API_KEY else 'disabled'
            },
            'train_data_count': len(LOCAL_TRAIN_DATA),
            'nearby_cities': NEARBY_CITIES
        }
        self.send_json_response(status)
    
    def send_cities(self):
        cities = list(NEARBY_CITIES.keys())
        self.send_json_response({'success': True, 'cities': cities})
    
    def send_test_response(self):
        self.send_json_response({
            'success': True,
            'message': '增强版服务器测试成功',
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'features': [
                '真实机票数据',
                '本地高铁数据',
                '周边城市对比',
                '智能推荐'
            ]
        })
    
    def send_search_result(self, data):
        origin = data.get('origin', '北京')
        destination = data.get('destination', '上海')
        date = data.get('date') or data.get('departure_date')
        optimization_type = data.get('optimization_type', 'time')
        constraints = data.get('constraints', {})
        
        print(f"🔍 搜索请求: {origin} → {destination} ({date})")
        
        routes = []
        source = 'mock'
        
        # 1) 获取机票数据
        flights = []
        if _juhe_flight_client:
            try:
                flight_date = date or datetime.now().strftime('%Y-%m-%d')
                
                # 城市名到IATA代码映射
                city_to_iata = {
                    '大连': 'DLC', '北京': 'PEK', '上海': 'PVG', '广州': 'CAN',
                    '深圳': 'SZX', '成都': 'CTU', '重庆': 'CKG', '西安': 'XIY',
                    '武汉': 'WUH', '南京': 'NKG', '杭州': 'HGH', '天津': 'TSN',
                    '青岛': 'TAO', '厦门': 'XMN', '长沙': 'CSX', '郑州': 'CGO',
                    '合肥': 'HFE', '济南': 'TNA', '福州': 'FOC', '南昌': 'KHN',
                    '石家庄': 'SJW', '太原': 'TYN', '呼和浩特': 'HET', '沈阳': 'SHE',
                    '长春': 'CGQ', '哈尔滨': 'HRB', '昆明': 'KMG', '贵阳': 'KWE',
                    '南宁': 'NNG', '海口': 'HAK', '三亚': 'SYX', '兰州': 'LHW',
                    '西宁': 'XNN', '银川': 'INC', '乌鲁木齐': 'URC', '拉萨': 'LXA'
                }
                
                # 获取IATA代码
                dep_code = city_to_iata.get(origin, origin)
                arr_code = city_to_iata.get(destination, destination)
                
                # 主要航班查询
                flights = _juhe_flight_client.query(dep_code, arr_code, flight_date)
                
                # 周边城市航班查询
                nearby_origins = NEARBY_CITIES.get(origin, [])
                nearby_destinations = NEARBY_CITIES.get(destination, [])
                
                # 查询出发地周边城市到目的地的航班
                for nearby_origin in nearby_origins[:2]:
                    nearby_code = city_to_iata.get(nearby_origin, nearby_origin)
                    nearby_flights = _juhe_flight_client.query(nearby_code, arr_code, flight_date)
                    for flight in nearby_flights:
                        flight['is_nearby'] = True
                        flight['nearby_type'] = 'origin'
                        flight['nearby_city'] = nearby_origin
                        flight['origin'] = f"{nearby_origin}({origin}附近)"
                    flights.extend(nearby_flights)
                
                # 查询出发地到目的地周边城市的航班
                for nearby_dest in nearby_destinations[:2]:
                    nearby_code = city_to_iata.get(nearby_dest, nearby_dest)
                    nearby_flights = _juhe_flight_client.query(dep_code, nearby_code, flight_date)
                    for flight in nearby_flights:
                        flight['is_nearby'] = True
                        flight['nearby_type'] = 'destination'
                        flight['nearby_city'] = nearby_dest
                        flight['destination'] = f"{nearby_dest}({destination}附近)"
                    flights.extend(nearby_flights)
                
                source += '+juhe_flight' if source != 'mock' else 'juhe_flight'
                
            except Exception as e:
                print(f"❌ 航班查询异常: {e}")
        
        # 2) 获取高铁数据
        trains = []
        # 从本地数据筛选
        for train in LOCAL_TRAIN_DATA:
            if (train['origin'] == origin and train['destination'] == destination):
                trains.append(train)
        
        # 周边城市高铁查询
        nearby_origins = NEARBY_CITIES.get(origin, [])
        nearby_destinations = NEARBY_CITIES.get(destination, [])
        
        for nearby_origin in nearby_origins[:2]:
            for train in LOCAL_TRAIN_DATA:
                if (train['origin'] == nearby_origin and train['destination'] == destination):
                    train_copy = train.copy()
                    train_copy['is_nearby'] = True
                    train_copy['nearby_type'] = 'origin'
                    train_copy['nearby_city'] = nearby_origin
                    train_copy['origin'] = f"{nearby_origin}({origin}附近)"
                    trains.append(train_copy)
        
        for nearby_dest in nearby_destinations[:2]:
            for train in LOCAL_TRAIN_DATA:
                if (train['origin'] == origin and train['destination'] == nearby_dest):
                    train_copy = train.copy()
                    train_copy['is_nearby'] = True
                    train_copy['nearby_type'] = 'destination'
                    train_copy['nearby_city'] = nearby_dest
                    train_copy['destination'] = f"{nearby_dest}({destination}附近)"
                    trains.append(train_copy)
        
        # 3) 合并和排序数据
        all_routes = []
        
        # 处理航班数据
        for flight in flights:
            route = {
                'type': 'flight',
                'flight_number': flight.get('flight_number', ''),
                'airline': flight.get('airline', ''),
                'origin': flight.get('origin', origin),
                'destination': flight.get('destination', destination),
                'dep_time': flight.get('departure_time', ''),
                'arr_time': flight.get('arrival_time', ''),
                'price': flight.get('price', 0),
                'dep_airport': flight.get('dep_airport', ''),
                'arr_airport': flight.get('arr_airport', ''),
                'duration': calculate_duration(flight.get('departure_time', ''), flight.get('arrival_time', '')),
                'is_nearby': flight.get('is_nearby', False),
                'nearby_type': flight.get('nearby_type', ''),
                'nearby_city': flight.get('nearby_city', ''),
                'source': '聚合数据API',
                'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            }
            all_routes.append(route)
        
        # 处理高铁数据
        for train in trains:
            route = {
                'type': 'train',
                'train_number': train.get('train_number', ''),
                'train_type': train.get('train_type', ''),
                'origin': train.get('origin', origin),
                'destination': train.get('destination', destination),
                'dep_time': train.get('dep_time', ''),
                'arr_time': train.get('arr_time', ''),
                'price': train.get('price', 0),
                'dep_station': train.get('dep_station', ''),
                'arr_station': train.get('arr_station', ''),
                'duration': calculate_duration(train.get('dep_time', ''), train.get('arr_time', '')),
                'is_nearby': train.get('is_nearby', False),
                'nearby_type': train.get('nearby_type', ''),
                'nearby_city': train.get('nearby_city', ''),
                'source': train.get('source', '本地数据'),
                'crawl_time': train.get('crawl_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            }
            all_routes.append(route)
        
        # 智能排序
        if optimization_type == 'price':
            all_routes.sort(key=lambda x: x.get('price', 0))
        elif optimization_type == 'time':
            all_routes.sort(key=lambda x: self._parse_time_for_sort(x.get('dep_time', '')))
        else:  # comprehensive
            # 综合排序：价格权重60%，时间权重40%
            for route in all_routes:
                price_score = 1000 - route.get('price', 0)
                time_score = self._calculate_time_score(route.get('dep_time', ''))
                nearby_penalty = -50 if route.get('is_nearby', False) else 0
                route['smart_score'] = price_score * 0.6 + time_score * 0.4 + nearby_penalty
            
            all_routes.sort(key=lambda x: x.get('smart_score', 0), reverse=True)
        
        # 优先显示非周边城市的结果
        all_routes.sort(key=lambda x: x.get('is_nearby', False))
        
        # 统计信息
        flights_count = len([x for x in all_routes if x.get('type') == 'flight'])
        trains_count = len([x for x in all_routes if x.get('type') == 'train'])
        nearby_count = len([x for x in all_routes if x.get('is_nearby', False)])
        
        result = {
            'success': True,
            'data': all_routes,
            'total': len(all_routes),
            'flights': flights_count,
            'trains': trains_count,
            'nearby': nearby_count,
            'optimization_type': optimization_type,
            'source': source,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        
        print(f"✅ 搜索完成: 找到 {len(all_routes)} 条结果（航班 {flights_count}，火车 {trains_count}，周边 {nearby_count}）")
        self.send_json_response(result)
    
    def _parse_time_for_sort(self, time_str):
        """解析时间字符串用于排序"""
        try:
            if time_str:
                if len(time_str) == 5:  # HH:MM格式
                    return datetime.strptime(time_str, '%H:%M')
                else:  # 完整日期时间格式
                    return datetime.strptime(str(time_str), '%Y-%m-%d %H:%M')
        except:
            pass
        return datetime.now()
    
    def _calculate_time_score(self, time_str):
        """计算时间分数"""
        try:
            if time_str:
                if len(time_str) == 5:  # HH:MM格式
                    time_obj = datetime.strptime(time_str, '%H:%M')
                else:  # 完整日期时间格式
                    time_obj = datetime.strptime(str(time_str), '%Y-%m-%d %H:%M')
                
                hour = time_obj.hour
                # 早上8-10点，下午2-4点分数最高
                if 8 <= hour <= 10 or 14 <= hour <= 16:
                    return 100
                elif 6 <= hour <= 8 or 10 <= hour <= 14 or 16 <= hour <= 18:
                    return 80
                else:
                    return 60
        except:
            pass
        return 50
    
    def send_poi_search(self, data):
        keyword = data.get('keyword', '餐厅')
        city = data.get('city', '北京')
        pois = []
        for i in range(5):
            pois.append({
                'name': f'{keyword}{i + 1}',
                'type': keyword,
                'address': f'{(city or "北京")}示例地址{i + 1}',
                'location': f'116.39{i}{i},39.90{i}{i}'
            })
        self.send_json_response({'success': True, 'pois': pois})
    
    def send_geocode(self, data):
        address = data.get('address', '')
        # 优先高德封装
        if _gaode_api and address:
            try:
                loc = _gaode_api.geocode(address)
                if loc:
                    lng, lat = loc
                    self.send_json_response({
                        'success': True,
                        'coordinates': {'lng': lng, 'lat': lat},
                        'address': address
                    })
                    return
            except Exception:
                pass
        # 直连一次
        if GAODE_KEY and address:
            try:
                url = 'https://restapi.amap.com/v3/geocode/geo'
                r = requests.get(url, params={'key': GAODE_KEY, 'address': address, 'output': 'json'}, timeout=8)
                dj = r.json()
                if dj.get('status') == '1' and dj.get('geocodes'):
                    loc = dj['geocodes'][0].get('location', '')
                    if loc and ',' in loc:
                        lng, lat = [float(x) for x in loc.split(',')]
                        self.send_json_response({'success': True,'coordinates': {'lng': lng, 'lat': lat},'address': address})
                        return
            except Exception:
                pass
        # 回退固定坐标
        self.send_json_response({
            'success': True,
            'coordinates': {'lng': 116.3974, 'lat': 39.9093},
            'address': address
        })
    
    def send_json_response(self, data):
        self.send_response(200)
        self.send_header('Content-type', 'application/json; charset=utf-8')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()
        
        json_data = json.dumps(data, ensure_ascii=False, indent=2)
        self.wfile.write(json_data.encode('utf-8'))

if __name__ == '__main__':
    PORT = 5000
    
    print("=" * 60)
    print("启动增强版HTTP服务器")
    print("=" * 60)
    print(f"服务地址: http://localhost:{PORT}")
    print(f"测试地址: http://localhost:{PORT}/api/test")
    print(f"城市列表: http://localhost:{PORT}/api/cities")
    print(f"前端页面: http://localhost:{PORT}/frontend/index.html")
    print(f"高铁数据: {len(LOCAL_TRAIN_DATA)} 条")
    print("=" * 60)
    print("按 Ctrl+C 停止服务")
    print("=" * 60)
    
    try:
        # 自动打开浏览器到前端页面
        try:
            webbrowser.open(f"http://localhost:{PORT}/frontend/index.html")
        except Exception:
            pass
        with socketserver.TCPServer(("", PORT), MyHTTPRequestHandler) as httpd:
            httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n服务器已停止")
    except Exception as e:
        print(f"服务器启动失败: {e}")